/* Copyright 2017, 2018, 2019, 2020 Gabriel Czernikier
 *
 * This file is part of Côtehaus.
 * Côtehaus is free software: you can redistribute it and/or modify
 * it under the terms of one of the following:
 * 1. The same dual license as that of Côtehaus itself, of which individual licenses are
 * the MIT License and the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 2. The MIT License.
 * 3. The GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * Côtehaus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * MIT License and the GNU General Public License for more details.
 * You should have received a copy of the MIT License and the GNU General Public License
 * along with Côtehaus.  If not, see <https://opensource.org/licenses/MIT> and <http://www.gnu.org/licenses/>.
 */
#ifndef __CH_JAVA7_H
#define __CH_JAVA7_H
#include "composer.h"
#include "type_id.h"
#include "types.h"

// Represent the portion of code that tops (caps) the Java program.
struct top_code_st {
	struct ident_st *package; // NULL if default package
	struct list_head imports_head;   // "import bar.blah.Baz" "import bar.*"
	struct context_st *context;
	struct list_head top_code_list;
};

struct context_st {
	struct list_head referentials_head;   //  "class A", "interface B" and "enum C" are all examples of referential.
	struct list_head subcontext_head;  //  for example "class A { subcontext of A }"
	struct list_head subcontext_list;
	struct context_st *enclosing;  // for example "class enclosing { class Foo {} }"
	struct mayqualif_schent *reftials_inctx; // referentials in context, searchable entries
};

enum ref_kind_en {
	class_ref, interface_ref, enum_ref;
};

enum ref_access_en {
	public_ref, private_ref, protected_ref, package_ref;
};

struct referential_st {
	lgwseq_t name;
	bool static_; // "static (class|interface|enum) Foo"
	enum ref_kind_en kind;
	enum ref_access_en access;
	struct list_head referential_list;
};

struct ident_st {
	lgwseq_t ident;
	struct list_head ident_list;
};

int ident_st_compar(struct ident_st*, struct ident_st*);

enum import_kind_en {
	reftyp_import, reftyp_glob_import, member_import, member_glob_import;
};

struct import_st {
	struct ident_st import;
	enum import_kind_en kind;
	struct list_head imports_list;
};

struct ident_st *add_ident(struct ident_st *what, struct ident_st *where);
struct ident_st *init_ident(lgwseq_t ident);
struct top_code_st *init_top_code();
void set_package(struct ident_st *package, struct top_code_st *top_code);
void add_import(struct ident_st *import, enum import_kind_en kind, struct top_code_st *top_code);
struct context_st *get_context(struct top_code_st *top_code);
struct context_st *open_context(struct context_st *current_context);
struct context_st *close_context(struct context_st *subcontext);
void add_referential(lgwseq_t name, struct context_st *where);

void build_opackage_ary();
void build_oimport_ary();

#endif
